package com.closer.codebox.biz;

import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.concurrent.TimeUnit;

// 内存监控服务类
@Service
@Slf4j
public class MemoryMonitorService {

    /**
     * 获取进程的内存使用情况（KB）
     */
    public long getProcessMemoryUsage(long pid) {
        try {
            var os = System.getProperty("os.name").toLowerCase();

            ProcessBuilder pb;
            if (os.contains("win")) {
                pb = new ProcessBuilder("wmic", "process", "where", "processid=" + pid,
                        "get", "WorkingSetSize");
            } else {
                // Linux/Mac: 使用RSS (Resident Set Size)
                pb = new ProcessBuilder("ps", "-o", "rss=", "-p", String.valueOf(pid));
            }

            Process process = pb.start();
            StringBuilder output = new StringBuilder();

            try (var reader = new BufferedReader(new InputStreamReader(process.getInputStream()))) {
                String line;
                while ((line = reader.readLine()) != null) {
                    if (!line.trim().isEmpty()) {
                        output.append(line.trim()).append("\n");
                    }
                }
            }

            // 读取错误流，避免进程阻塞
            try (var errorReader = new BufferedReader(new InputStreamReader(process.getErrorStream()))) {
                while (errorReader.readLine() != null) {
                    // 消耗错误流
                }
            }

            boolean finished = process.waitFor(2, TimeUnit.SECONDS);
            if (!finished) {
                process.destroyForcibly();
                return 0;
            }

            return parseMemoryOutput(output.toString().trim(), os);

        } catch (Exception e) {
            log.warn("监控进程内存失败 PID {}: {}", pid, e.getMessage());
            return 0;
        }
    }

    private long parseMemoryOutput(String output, String os) {
        if (output == null || output.isEmpty()) {
            return 0;
        }

        try {
            if (os.contains("win")) {
                // Windows输出格式: WorkingSetSize \n 12345678
                String[] lines = output.split("\\r?\\n");
                for (String line : lines) {
                    line = line.trim();
                    if (!line.isEmpty() && Character.isDigit(line.charAt(0))) {
                        long memory = Long.parseLong(line);
                        return memory / 1024; // 转换为KB
                    }
                }
            } else {
                // Linux/Mac: 直接输出RSS值（KB）
                String[] parts = output.split("\\s+");
                for (String part : parts) {
                    part = part.trim();
                    if (!part.isEmpty() && Character.isDigit(part.charAt(0))) {
                        return Long.parseLong(part);
                    }
                }
            }
        } catch (NumberFormatException e) {
            log.warn("解析内存输出失败: {}", output);
        }

        return 0;
    }

    /**
     * 实时监控进程内存峰值
     */
    public long monitorPeakMemory(long pid, long timeoutMs) {
        long startTime = System.currentTimeMillis();
        long peakMemory = 0;
        int checkCount = 0;

        while (System.currentTimeMillis() - startTime < timeoutMs) {
            try {
                long currentMemory = getProcessMemoryUsage(pid);
                if (currentMemory > 0) {
                    peakMemory = Math.max(peakMemory, currentMemory);
                    checkCount++;
                }

                // 检查进程是否还存在
                if (!isProcessAlive(pid)) {
                    break;
                }

                Thread.sleep(30); // 每30ms检查一次
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
                break;
            } catch (Exception e) {
                // 进程可能已结束
                break;
            }
        }

        log.debug("监控进程 {} 完成，检查次数: {}, 峰值内存: {}KB", pid, checkCount, peakMemory);
        return peakMemory;
    }

    /**
     * 检查进程是否存活
     */
    private boolean isProcessAlive(long pid) {
        try {
            var os = System.getProperty("os.name").toLowerCase();
            ProcessBuilder pb;

            if (os.contains("win")) {
                pb = new ProcessBuilder("tasklist", "/FI", "PID eq " + pid);
            } else {
                pb = new ProcessBuilder("ps", "-p", String.valueOf(pid));
            }

            Process process = pb.start();
            boolean finished = process.waitFor(1, TimeUnit.SECONDS);

            if (finished) {
                return process.exitValue() == 0;
            }
        } catch (Exception e) {
            // 忽略异常
        }
        return false;
    }
}